package pt.um.jspecput.lib.writer;

import static pt.um.jspecput.util.Constants.*;

import java.io.IOException;
import java.io.Writer;

import com.google.common.base.Strings;

/**
 * The Class ClassWriter hols methods that write a java class.
 */
public abstract class ClassWriterHelper {

    /**
     * Write the package declaration to a file.
     * 
     * @param writer
     *            the writer for the file
     * @param packageName
     *            the package name
     * @throws IOException
     *             Signals that an I/O exception has occurred.
     */
    public static void writePackage(Writer writer, String packageName)
            throws IOException {
        String fullLine = "package " + packageName + SEMICOLUMN;

        writer.write(fullLine);
    }

    /**
     * Writes an import declaration to a file.
     * 
     * @param writer
     *            the writer for the file
     * @param importedClass
     *            the imported class
     * @throws IOException
     *             Signals that an I/O exception has occurred.
     */
    public static void writeImport(Writer writer, String importedClass)
            throws IOException {
        String fullLine = "import " + importedClass + SEMICOLUMN;

        writer.write(fullLine);
    }

    /**
     * Writes a static import declaration.
     * 
     * @param writer
     *            the writer for the file
     * @param importedMembers
     *            the imported methods
     * @throws IOException
     *             Signals that an I/O exception has occurred.
     */
    public static void writeStaticImport(Writer writer, String importedMembers)
            throws IOException {
        String fullLine = "import static " + importedMembers + SEMICOLUMN;

        writer.write(fullLine);
    }

    /**
     * Writes a class declaration.
     * 
     * @param writer
     *            the writer for the file
     * @param access
     *            the access level for the class, null for none
     * @param modifier
     *            the modifier if the class is abstract or final, null for
     *            neither
     * @param className
     *            the class name
     * @throws IOException
     *             Signals that an I/O exception has occurred.
     */
    protected static void openClassDeclaration(Writer writer, String access,
            String modifier, String className) throws IOException {
        StringBuilder sb = new StringBuilder();
        if (!Strings.isNullOrEmpty(access)) {
            sb.append(access + SPACE_CHARACTER);
        }
        if (!Strings.isNullOrEmpty(modifier)) {
            sb.append(modifier + SPACE_CHARACTER);
        }
        sb.append("class" + SPACE_CHARACTER);
        sb.append(className + SPACE_CHARACTER);
        sb.append(OPEN_CURLY_BRACKET);

        writer.write(sb.toString());
    }

    /**
     * Writes a public class declaration.
     * 
     * @param writer
     *            the writer
     * @param className
     *            the class name
     * @throws IOException
     *             Signals that an I/O exception has occurred.
     */
    public static void openPublicClassDeclaration(Writer writer,
            String className) throws IOException {
        openClassDeclaration(writer, PUBLIC, null, className);
    }

    /**
     * Writes a public abstract class declaration.
     * 
     * @param writer
     *            the writer
     * @param className
     *            the class name
     * @throws IOException
     *             Signals that an I/O exception has occurred.
     */
    public static void openPublicAbstractClassDeclaration(Writer writer,
            String className) throws IOException {
        openClassDeclaration(writer, PUBLIC, ABSTRACT, className);
    }

    /**
     * Writes a public final class declaration.
     * 
     * @param writer
     *            the writer
     * @param className
     *            the class name
     * @throws IOException
     *             Signals that an I/O exception has occurred.
     */
    public static void openPublicFinalClassDeclaration(Writer writer,
            String className) throws IOException {
        openClassDeclaration(writer, PUBLIC, FINAL, className);
    }

    /**
     * Writes a class declaration.
     * 
     * @param writer
     *            the writer
     * @param className
     *            the class name
     * @throws IOException
     *             Signals that an I/O exception has occurred.
     */
    public static void openClassDeclaration(Writer writer, String className)
            throws IOException {
        openClassDeclaration(writer, null, null, className);
    }

    /**
     * Writes a abstract class declaration.
     * 
     * @param writer
     *            the writer
     * @param className
     *            the class name
     * @throws IOException
     *             Signals that an I/O exception has occurred.
     */
    public static void openAbstractClassDeclaration(Writer writer,
            String className) throws IOException {
        openClassDeclaration(writer, null, ABSTRACT, className);
    }

    /**
     * Writes a final class declaration.
     * 
     * @param writer
     *            the writer
     * @param className
     *            the class name
     * @throws IOException
     *             Signals that an I/O exception has occurred.
     */
    public static void openFinalClassDeclaration(Writer writer, String className)
            throws IOException {
        openClassDeclaration(writer, null, FINAL, className);
    }

    /**
     * Closes a class declaration.
     * 
     * @param writer
     *            the writer for the file
     * @throws IOException
     *             Signals that an I/O exception has occurred.
     */
    public static void closeClassDeclaration(Writer writer) throws IOException {
        writer.write(CLOSE_CURLY_BRACKET);
    }
}